﻿
#include <cassert>
#include <iostream>
#include <string>
using namespace std;

#include <windows.h>
#include "Grammer.h"
//=================================================


extern const char prefix[] = "jisuan:";

template <typename T>
void PrintRange(T begin, T end)
{
	//for (T c = begin; c < end; c++)
	//{
	//	cout<<*c;
	//}
	//cout<<std::endl;
}

/*
void PrintRange(const wchar_t * begin, const wchar_t * end)
{
	for (const wchar_t * c = begin; c < end; c++)
	{
		wcout<<*c;
	}
}
*/

//class formater
//{
//	enum { MAX_BUFLENGTH = 1024 };
//public:
//	formater(const char * fmt, ...)
//	{
//		va_list va;
//		va_start(va, fmt);
//		vsnprintf(m_formatedStr, formater::MAX_BUFLENGTH, fmt, va);
//		va_end(va);
//		return;
//	}
//public:
//	operator const char *() const
//	{
//		return m_formatedStr;
//	}
//private:
//	char m_formatedStr[MAX_BUFLENGTH];
//};

//=================================================


BEGIN_REDUCER(Expr)
	HAVE_POSTFIX(Element_BlankSpaces);
	PrintRange(begin, last);
	//cout<<":Expr"<<endl;
	return true;
END_REDUCER

BEGIN_REDUCER(Token_Lbracket)
	HAVE_POSTFIX(Element_BlankSpaces);
	PrintRange(begin, last);
	//cout<<":("<<endl;
	//context.level++;
	return true;
END_REDUCER

BEGIN_REDUCER(Token_Rbracket)
	HAVE_POSTFIX(Element_BlankSpaces);
	PrintRange(begin, last);
	//cout<<":)"<<endl;
	//context.level--;
	return true;
END_REDUCER

BEGIN_REDUCER(Token_IntegerNumber)
	HAVE_POSTFIX(Element_BlankSpaces);
	PrintRange(begin, last);
	//cout<<":integer"<<endl;
	context.push();
//	*((int*)newbase) = atoi(begin);
//	context->archive(sizeof(int));
//	context->PushData(Dataunit<Element_IntegerNumver>(1000));
//	context->commit(2, begin, *end);
	return true;
END_REDUCER


BEGIN_REDUCER(Token_FloatingNumber)
	HAVE_POSTFIX(Element_BlankSpaces);
	PrintRange(begin, last);
	//cout<<":floating"<<endl;	
	context.push();
//	*((double*)newbase) = atof(begin);
//	context->archive(sizeof(double));
//		context->commit(3, begin, *end);
	return true;
END_REDUCER


BEGIN_REDUCER(Element_Operator)
	HAVE_POSTFIX(Element_BlankSpaces);
	PrintRange(begin, last);
	//cout<<":operator"<<endl;
	context.push();
	//while (*last == ' ') last++;
	Element_AnySep::shift(context, last, &last);
	return true;
END_REDUCER


BEGIN_REDUCER(Term)
	HAVE_POSTFIX(Element_BlankSpaces);
	PrintRange(begin, last);
	//cout<<":Term"<<endl;
	return true;
END_REDUCER


BEGIN_REDUCER(Factor)
	HAVE_POSTFIX(Element_BlankSpaces);
	PrintRange(begin, last);
	//cout<<":Factor"<<endl;
	return true;
END_REDUCER

BEGIN_REDUCER(Token_String)
	HAVE_POSTFIX(Element_BlankSpaces);
	PrintRange(begin, last);	
	//cout<<":String"<<endl;
	context.push();
	return true;
END_REDUCER


BEGIN_REDUCER(MulOp)
	HAVE_POSTFIX(Element_BlankSpaces);
	PrintRange(begin, last);
	//cout<<":op(mul)"<<endl;
	context.push();
	return true;
END_REDUCER

BEGIN_REDUCER(AddOp)
	HAVE_POSTFIX(Element_BlankSpaces);
	PrintRange(begin, last);
	//cout<<":op(add)"<<endl;
	context.push();
	return true;
END_REDUCER

BEGIN_REDUCER(nulltoken)
	HAVE_POSTFIX(Element_BlankSpaces);
	PrintRange(begin, last);
	//cout<<":null"<<endl;
	return true;
END_REDUCER


BEGIN_REDUCER(Element_DecNumber)
	HAVE_POSTFIX(Element_BlankSpaces);

	PrintRange(begin, last);
	ptrdiff_t session = context.checkout();
	//cout<<":digit"<<endl;
	context.push();
	context.submit(session);
	return true;
END_REDUCER


#include <vector>
#include <string>
using namespace std;

class TestContext:public context
{
	enum { MAX_BUFLENGTH = 1024 };
public:
	TestContext():stacktop(0) {m_formatedStr[0] = '\0';}
	virtual ~TestContext() {;}
public:
	ptrdiff_t checkout()
	{
		printf("prepare at %d.\n", stacktop);
		return stacktop++;
	}

	void revert(ptrdiff_t session)
	{
		printf("rollback to %d.\n", session);
		stacktop = (int)session;
	}

	void submit(ptrdiff_t)
	{
		stacktop += 1;
		printf("commit to %d.\n", stacktop);
	}

	void push()
	{
		stacktop += 1;
		printf("push a item to %d.\n", stacktop);
	}

	void fault(void * offset)
	{
		std::string::iterator it = *(std::string::iterator*)offset;
		_snprintf_c(m_formatedStr, MAX_BUFLENGTH, "fault at '%s'(%d).", it.operator->(), it.operator->());
	}

	void dump_error()
	{
		printf("%s\n", m_formatedStr);
	}

private:
	int	 stacktop;
	char m_formatedStr[MAX_BUFLENGTH];
};


int main()
{
	TestContext context;

	std::string buffer;
	buffer.resize(4096);
	//for(;;)
	{
		//cin.getline((char*)buffer.c_str(), 4096);
		buffer = "jisuan:1+2* 2342+    98942*  (   243-  3483)+( 232+(347-3999 * (23-555))  )  ";
		//buffer = "jisuan:1+2";
		//buffer = "jisuan:1+2E10EOF";
		buffer.push_back('\0');

		std::string::iterator end;

		const unsigned LOOPS = 1;
		unsigned long duration = GetTickCount();
		for (int i = 0; i < LOOPS; i++)
		{
			if (!parser<MyExpr>::parse(context, buffer.begin(), &end))
			{
				context.dump_error();
			}
		}
		duration = GetTickCount() - duration;

		printf("Used time: %d ms, total bytes: %d bytes, average: %.4lf MBps\n", duration, (end - buffer.begin())*LOOPS, ((end - buffer.begin())*LOOPS/1024.0/1024.0)/(duration/1000.0));
		if (*end == '\0')
		{
			printf("EOF.\n");
		}
		else
		{
			printf("Not Finished:\n");
			context.dump_error();
		}
	}

	return 0;
}




